package com.itdct.onflow.core.service

import com.baomidou.mybatisplus.extension.plugins.pagination.Page
import com.itdct.onflow.core.constant.CommonString
import com.itdct.onflow.core.constant.ReturnCode
import com.itdct.onflow.core.context.BaseContext
import com.itdct.onflow.core.context.ContextHolder
import com.itdct.onflow.core.dto.BaseLoginDTO
import com.itdct.onflow.core.exception.CommonException
import com.itdct.onflow.core.extend.logWarn
import com.itdct.onflow.core.vo.RespPageVo
import com.itdct.onflow.core.vo.RespVo
import org.springframework.stereotype.Service

/**
 * @author Zhouwx
 * @date 2024/4/15 14:34:50
 * @version 1.0
 * @description
 */
@Service
class BaseService<AccountEntity : Any, LoginDTO : BaseLoginDTO<AccountEntity>>() {

    // INFO: Zhouwx: 2024/4/16 throw表达式的返回值类型是Nothing。这种类型没有值，用于标记永远无法到达的代码位置。在你自己的代码中，你可以使用Nothing来标记一个永远不返回的函数
    @Throws(CommonException::class)
    fun fail(info: String = "系统出错，请稍后再试"): Nothing {
        throw CommonException(ReturnCode.SYSTEM_ERROR, info)
    }

    // INFO: Zhouwx: 2024/4/16 throw表达式的返回值类型是Nothing。这种类型没有值，用于标记永远无法到达的代码位置。在你自己的代码中，你可以使用Nothing来标记一个永远不返回的函数
    @Throws(CommonException::class)
    fun fail(code: Int = ReturnCode.SYSTEM_ERROR, info: String = "系统出错，请稍后再试", data: Any? = null): Nothing {
        throw CommonException(code, info)
    }

    fun <R> success(data: R? = null, code: Int = ReturnCode.SUCCESS, info: String = CommonString.SUCCESS): RespVo<R> {
        return RespVo(code, data, info)
    }

    fun <T> successPage(pageData: List<T>): RespPageVo<T> {
        val context: BaseContext<AccountEntity, BaseLoginDTO<AccountEntity>>? = getContext()
        if (context == null) {
            throw CommonException("context is null")
        }
        val page: Page<*>? = context.page
        if (page != null) {
            return RespPageVo(pageData, page.current, page.size, page.total, page.pages)
        } else {
            logWarn("page is null!")
            return RespPageVo(pageData, 0L, 0L, 0L, 0L)
        }
    }

    fun getContext(): BaseContext<AccountEntity, BaseLoginDTO<AccountEntity>>? {
        val context: BaseContext<AccountEntity, BaseLoginDTO<AccountEntity>>? = ContextHolder.getContext()
        return context
    }

    fun checkSelfPermission(context: BaseContext<AccountEntity, BaseLoginDTO<AccountEntity>>, checkId: Long) {
        val accountId = context.accountId ?: fail(ReturnCode.UNAUTHORIZED, "请登录后使用")
        if (accountId != checkId) {
            fail(ReturnCode.PERMISSION_FORBIDDEN, CommonString.PERMISSION_FORBIDDEN)
        }
    }

}